//
//  ImageEditorController.m
//  YuanXinCamera
//
//  Created by GJS on 2018/3/16.
//  Copyright © 2018年 晏德智. All rights reserved.
//

#import "ImageEditorController.h"
#import "TOCropViewController.h"
#import "NSBundle+TZImagePicker.h"

@interface ImageEditorController () <TOCropViewControllerDelegate>

@property (nonatomic, strong) UIImageView *imageView;    // The image view to present the cropped image
@property (nonatomic, strong) UIButton *cropStyleButton; // The button to choose a crop style

@property (nonatomic, assign) ImageEditorCropViewCroppingStyle croppingStyle; //The cropping style
@property (nonatomic, assign) CGRect croppedFrame;
@property (nonatomic, assign) NSInteger angle;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@property (nonatomic, strong) UIPopoverController *activityPopoverController;
#pragma clang diagnostic pop

@end

@implementation ImageEditorController

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.imageView = [[UIImageView alloc] init];
        self.wetherAddChildEditorVC = YES;
        self.autoDismiss = YES;
    }
    return self;
}

#pragma mark - View Creation/Lifecycle -
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBar.translucent = NO;
    
    if (self.childEditorVC) {
        
        //加在同一个页面，或者用两个页面也可以
        if (self.wetherAddChildEditorVC) {
            [self addChildViewController:self.childEditorVC];
            [self.view addSubview:self.childEditorVC.view];
            return;
        }
        
        /* pushViewController or presentViewController
        //If profile picture, push onto the same navigation stack
        if (self.croppingStyle == TOCropViewCroppingStyleCircular) {
            [self.navigationController pushViewController:self.childEditorVC animated:YES];
        }
        else { //otherwise dismiss, and then present from the main controller
            [self dismissViewControllerAnimated:YES completion:^{
                [self presentViewController:self.childEditorVC animated:YES completion:nil];
                //[self.navigationController pushViewController:cropController animated:YES];
            }];
        }
         */
    }
    
    self.title = [NSBundle tz_localizedStringForKey:@"Crop Image"];
    
    // Bar Button Items
    /*
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showCropViewController)];
    
#if TARGET_APP_EXTENSION
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(dismissViewController)];
#else
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(sharePhoto)];
    self.navigationItem.rightBarButtonItem.enabled = NO;
#endif
    */
    
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneClicked)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelClicked)];
    
    self.cropStyleButton = [UIButton buttonWithType:UIButtonTypeCustom];
    self.cropStyleButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
    self.cropStyleButton.titleLabel.font = [UIFont systemFontOfSize:14];
    [self.cropStyleButton setTitle:[NSBundle tz_localizedStringForKey:@"Choose crop style"] forState:UIControlStateNormal];
    [self.cropStyleButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [self.cropStyleButton setTitleColor:[UIColor colorWithWhite:1 alpha:0.5] forState:UIControlStateHighlighted];
    [self.cropStyleButton addTarget:self action:@selector(showCropViewController) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.cropStyleButton];
    
    self.imageView.userInteractionEnabled = YES;
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    [self.view addSubview:self.imageView];
    
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapImageView)];
    [self.imageView addGestureRecognizer:tapRecognizer];
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self layoutImageView];
    [self layoutCropStyleButton];
}

#pragma mark - getter/setter -
// 内部/默认 实现(采用 TOCropViewController)
- (UIViewController *)childEditorVC
{
    if (!_childEditorVC) {
        _childEditorVC = [self childEditorVCWithCroppingStyle:(TOCropViewCroppingStyle)self.croppingStyle];
    }
    
    return _childEditorVC;
}

- (CGRect)imageCropFrame {
    if (CGRectIsEmpty(_imageCropFrame)) {
        CGSize imageCropSize = [self imageSize];
        CGFloat minCropWidth = MIN(imageCropSize.width, imageCropSize.height);
        minCropWidth = MIN(minCropWidth, (MIN(self.view.bounds.size.width, self.view.bounds.size.height))/2);
        CGRect cropFrame = CGRectMake(0, 0, minCropWidth, minCropWidth);
        _imageCropFrame = cropFrame;
    }
    return _imageCropFrame;
}

- (CGSize)imageSize
{
    if (self.angle == -90 || self.angle == -270 || self.angle == 90 || self.angle == 270)
        return (CGSize){self.image.size.height, self.image.size.width};
    
    return (CGSize){self.image.size.width, self.image.size.height};
}

- (void)updateChildEditorVC {
    if ([_childEditorVC isKindOfClass:[TOCropViewController class]]) {
        [_childEditorVC removeFromParentViewController];
        ((TOCropViewController *)_childEditorVC).delegate = nil;
        _childEditorVC = nil;
        _childEditorVC = [self childEditorVCWithCroppingStyle:(TOCropViewCroppingStyle)self.croppingStyle];
        if (_childEditorVC) {
            [self addChildViewController:_childEditorVC];
            [self.view addSubview:_childEditorVC.view];
        }
    }
}

- (UIViewController *)childEditorVCWithCroppingStyle:(TOCropViewCroppingStyle)croppingStyle {
    if (!self.image) {
        return nil;
    }
    
    TOCropViewController *cropController = [[TOCropViewController alloc] initWithCroppingStyle:croppingStyle image:self.image];
    _childEditorVC = cropController;
    cropController.cropView.cropBoxResizeEnabled = self.cropBoxResizeEnabled;
    cropController.delegate = self;
    if (croppingStyle == CropViewCroppingStyleDefault && !self.cropBoxResizeEnabled) {
        //cropController.imageCropFrame = self.imageCropFrame; //The initial frame that the crop controller will have visible.
        
        cropController.aspectRatioPreset = TOCropViewControllerAspectRatioPresetSquare; //Set the initial aspect ratio as a square
        cropController.aspectRatioLockEnabled = YES; // The crop box is locked to the aspect ratio and can't be resized away from it
        cropController.resetAspectRatioEnabled = NO; // When tapping 'reset', the aspect ratio will NOT be reset back to default
    }
    
    // Uncomment this if you wish to provide extra instructions via a title label
    //cropController.title = @"Crop Image";
    
    // -- Uncomment these if you want to test out restoring to a previous crop setting --
    //cropController.angle = 90; // The initial angle in which the image will be rotated
    //cropController.imageCropFrame = CGRectMake(0,0,2848,4288); //The initial frame that the crop controller will have visible.
    
    // -- Uncomment the following lines of code to test out the aspect ratio features --
    //cropController.aspectRatioPreset = TOCropViewControllerAspectRatioPresetSquare; //Set the initial aspect ratio as a square
    //cropController.aspectRatioLockEnabled = YES; // The crop box is locked to the aspect ratio and can't be resized away from it
    //cropController.resetAspectRatioEnabled = NO; // When tapping 'reset', the aspect ratio will NOT be reset back to default
    //cropController.aspectRatioPickerButtonHidden = YES;
    
    // -- Uncomment this line of code to place the toolbar at the top of the view controller --
    //cropController.toolbarPosition = TOCropViewControllerToolbarPositionTop;
    
    //cropController.rotateButtonsHidden = YES;
    //cropController.rotateClockwiseButtonHidden = NO;
    
    //cropController.doneButtonTitle = @"Title";
    //cropController.cancelButtonTitle = @"Title";
    
    return _childEditorVC;
}
- (void)setImage:(UIImage *)image
{
    if (image && image != _image) {
        _image = image;
        self.imageView.image = _image;
        [self layoutImageView];
        // 更新 childEditorVC
        [self updateChildEditorVC];
    }
}

#pragma mark - Gesture Recognizer -
- (void)didTapImageView
{
    // When tapping the image view, restore the image to the previous cropping state
    TOCropViewController *cropController = [[TOCropViewController alloc] initWithCroppingStyle:(TOCropViewCroppingStyle)self.croppingStyle image:self.image];
    cropController.cropView.cropBoxResizeEnabled = self.cropBoxResizeEnabled;
    cropController.delegate = self;
    CGRect viewFrame = [self.view convertRect:self.imageView.frame toView:self.navigationController.view];
    [cropController presentAnimatedFromParentViewController:self
                                                  fromImage:self.imageView.image
                                                   fromView:nil
                                                  fromFrame:viewFrame
                                                      angle:self.angle
                                               toImageFrame:self.croppedFrame
                                                      setup:^{ self.imageView.hidden = YES; }
                                                 completion:^{ self.imageView.hidden = NO; }];
}

#pragma mark - Cropper Delegate -
- (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
    self.croppedFrame = cropRect;
    self.angle = angle;
    if (!self.wetherAddChildEditorVC) {
        [self updateImageViewWithImage:image fromCropViewController:cropViewController];
    } else {
        // call delegate
        if ([self.editorDelegate respondsToSelector:@selector(imageEditor:didFinishEdittingWithImage:)]) {
            [self.editorDelegate imageEditor:cropViewController didFinishEdittingWithImage:image];
        }
        [self dismissViewController:self];
    }
}

- (void)cropViewController:(TOCropViewController *)cropViewController didCropToCircularImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
    self.croppedFrame = cropRect;
    self.angle = angle;
    if (!self.wetherAddChildEditorVC) {
        [self updateImageViewWithImage:image fromCropViewController:cropViewController];
    } else {
        // call delegate
        if ([self.editorDelegate respondsToSelector:@selector(imageEditor:didFinishEdittingWithImage:)]) {
            [self.editorDelegate imageEditor:cropViewController didFinishEdittingWithImage:image];
        }
        [self dismissViewController:self];
    }
}

- (void)cropViewController:(TOCropViewController *)cropViewController didFinishCancelled:(BOOL)cancelled
{
    if (!self.wetherAddChildEditorVC) {
        [self dismissViewController:cropViewController];
    } else {
        // call delegate
        if ([self.editorDelegate respondsToSelector:@selector(imageEditorDidCancel:)]) {
            [self.editorDelegate imageEditorDidCancel:cropViewController];
        }
        [self dismissViewController:cropViewController];
    }
}

- (void)dismissViewController:(UIViewController *)viewController {
    if (self.autoDismiss) {
        if (viewController.navigationController) {
            [viewController.navigationController popViewControllerAnimated:YES];
        }
        else {
            viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
            [viewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
        }
    }
}

- (void)updateImageViewWithImage:(UIImage *)image fromCropViewController:(TOCropViewController *)cropViewController
{
    self.imageView.image = image;
    [self layoutImageView];
    
    self.navigationItem.rightBarButtonItem.enabled = YES;
    
    if (cropViewController.croppingStyle != TOCropViewCroppingStyleCircular) {
        self.imageView.hidden = YES;
        [cropViewController dismissAnimatedFromParentViewController:self
                                                   withCroppedImage:image
                                                             toView:self.imageView
                                                            toFrame:CGRectZero
                                                              setup:^{ [self layoutImageView]; }
                                                         completion:
         ^{
             self.imageView.hidden = NO;
         }];
    }
    else {
        self.imageView.hidden = NO;
        if (cropViewController.navigationController) {
            [cropViewController.navigationController popViewControllerAnimated:YES];
        }
        else {
            cropViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
            [cropViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
        }
    }
}

#pragma mark - Image Layout -
- (void)layoutImageView
{
    if (self.imageView.image == nil)
        return;
    
    CGFloat padding = 20.0f;
    
    CGRect viewFrame = self.view.bounds;
    viewFrame.size.width -= (padding * 2.0f);
    viewFrame.size.height -= ((padding * 2.0f));
    
    CGRect imageFrame = CGRectZero;
    imageFrame.size = self.imageView.image.size;
    
    if (self.imageView.image.size.width > viewFrame.size.width ||
        self.imageView.image.size.height > viewFrame.size.height)
    {
        CGFloat scale = MIN(viewFrame.size.width / imageFrame.size.width, viewFrame.size.height / imageFrame.size.height);
        imageFrame.size.width *= scale;
        imageFrame.size.height *= scale;
        imageFrame.origin.x = (CGRectGetWidth(self.view.bounds) - imageFrame.size.width) * 0.5f;
        imageFrame.origin.y = (CGRectGetHeight(self.view.bounds) - imageFrame.size.height) * 0.5f;
        self.imageView.frame = imageFrame;
    }
    else {
        self.imageView.frame = imageFrame;
        self.imageView.center = (CGPoint){CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds)};
    }
}

#pragma mark - Button Layout -
- (void)layoutCropStyleButton
{
    CGRect buttonFrame = CGRectZero;
    buttonFrame.size = CGSizeMake(180, 40);
    self.cropStyleButton.frame = buttonFrame;
    self.cropStyleButton.center = (CGPoint){CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds)-buttonFrame.size.height};
}

#pragma mark - Bar Button Items -
- (void)doneClicked
{
    // call delegate
    if ([self.editorDelegate respondsToSelector:@selector(imageEditor:didFinishEdittingWithImage:)]) {
        [self.editorDelegate imageEditor:self didFinishEdittingWithImage:self.imageView.image];
    }
    [self dismissViewController];
}

- (void)cancelClicked
{
    // call delegate
    if ([self.editorDelegate respondsToSelector:@selector(imageEditorDidCancel:)]) {
        [self.editorDelegate imageEditorDidCancel:self];
    }
    [self dismissViewController];
}

- (void)showCropViewController
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"Crop Image"]
                                                            style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction *action) {
                                                              self.croppingStyle = TOCropViewCroppingStyleDefault;
                                                              [self updateChildEditorVC];
                                                              
                                                              if (self.childEditorVC) {
                                                                  [self presentViewController:self.childEditorVC animated:YES completion:nil];
                                                              }
                                                          }];
    
    UIAlertAction *profileAction = [UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"Make Profile Picture"]
                                                            style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction *action) {
                                                              self.croppingStyle = TOCropViewCroppingStyleCircular;
                                                              [self updateChildEditorVC];
                                                              
                                                              if (self.childEditorVC) {
                                                                  [self.navigationController pushViewController:self.childEditorVC animated:YES];
                                                              }
                                                          }];
    
    [alertController addAction:defaultAction];
    [alertController addAction:profileAction];
    //iOS8之后使用UIAlertController 代替UIActionSheet, 如果不添加取消按钮, 点击空白处则不隐藏弹框;
    //所以点击空白处需要隐藏弹框的, 添加取消按钮即可.
    [alertController addAction:[UIAlertAction actionWithTitle:[NSBundle tz_localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]];
    [alertController setModalPresentationStyle:UIModalPresentationPopover];
    
    UIPopoverPresentationController *popPresenter = [alertController popoverPresentationController];
    popPresenter.barButtonItem = self.navigationItem.leftBarButtonItem;
    [self presentViewController:alertController animated:YES completion:nil];
}

- (void)sharePhoto
{
    if (self.imageView.image == nil)
        return;
    
    UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:@[self.imageView.image] applicationActivities:nil];
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        [self presentViewController:activityController animated:YES completion:nil];
    }
    else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [self.activityPopoverController dismissPopoverAnimated:NO];
        self.activityPopoverController = [[UIPopoverController alloc] initWithContentViewController:activityController];
        [self.activityPopoverController presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
#pragma clang diagnostic pop
    }
}

- (void)dismissViewController {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
